package services

import (
	"context"
	"fmt"
	"github.com/olivere/elastic/v7"
	"github.com/spf13/cast"
	global2 "longmen/server/config/global"
	"longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_live"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_live"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	"reflect"
	"sort"

	"github.com/jinzhu/copier"
	"longmen/server/pkg/common/api_models"
)

func (s *Service) SearchLiveOrAnchor(req *api_models.SearchReq) (resp api_models.SearchResp) {
	SearchReq := api_models.LiveOrAnchorSearchReq{
		Keyword: req.Keyword,
		PageParam: api_models.PageParam{
			Page: 1,
			Size: 10,
		},
		Uid: req.UID,
	}
	liveResp := make([]*api_models.LiveAnchor, 0)
	anchorResp := make([]*api_models.Anchor, 0)
	switch req.Type {
	case 1:
		liveResp, _ = s.live(&SearchReq)
	case 2:
		anchorResp, _ = s.searchAnchor(&SearchReq)
	default:
		liveResp, _ = s.live(&SearchReq)
		anchorResp, _ = s.searchAnchor(&SearchReq)
	}
	if len(anchorResp) > 0 {
		mGuess, _ := cache.GetGuessList()
		lives, _ := db_live.GetLivesParam(map[string]interface{}{}, "hot desc,start_stamp desc", 0, 100)
		for _, v := range lives {
			for _, l := range anchorResp {
				if v.Anchorid == l.Id {
					l.Living = 1
				}
			}
			for _, nodeLiveResp := range liveResp {
				iGuessTag := 0
				if mGuess != nil {
					if liveId, ok := (*mGuess)[nodeLiveResp.Anchorid]; ok && (liveId == nodeLiveResp.Liveid) {
						iGuessTag = 1
					}
				}
				nodeLiveResp.GuessTag = iGuessTag
			}
		}
	}
	sort.Slice(anchorResp, func(i, j int) bool {
		return anchorResp[i].Living > anchorResp[j].Living
	})
	resp.Lives = liveResp
	resp.Anhor = anchorResp
	return resp
}

func (s *Service) searchAnchor(req *api_models.LiveOrAnchorSearchReq) ([]*api_models.Anchor, error) {
	var query elastic.Query
	if e, err2 := cast.ToInt32E(req.Keyword); err2 == nil {
		query = elastic.NewTermQuery("id", e)
	} else {
		query = elastic.NewWildcardQuery("nick_name.keyword", fmt.Sprintf("*%s*", req.Keyword))
	}
	searchResult, err := global2.GetEs().Search().Index(_const.ES_Anchor).Query(query).Timeout(_const.ES_SEARCH_TIME_OUT).Size(10).Do(context.Background())
	if err != nil {
		global2.Log.Debugf("searchAnchor err:%v", err)
		return nil, err
	}
	global2.Log.Debugf("33333333U:%v,err:%v", query, err)
	anchor := make([]*api_models.Anchor, 0)
	if searchResult.TotalHits() > 0 {
		var b1 models_main.PartUser
		// 通过Each方法，将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			if val, ok := item.(models_main.PartUser); ok {
				isattent := 0
				if req.Uid > 0 {
					attentIds := cache.GetUserAttentAnchorIds(req.Uid)
					if string2.IntIsInSlice(attentIds, val.Id) {
						isattent = 1
					}
				}
				anchor = append(anchor, &api_models.Anchor{
					PartUser: val,
					FansNum:  cache.GetFansCount(val.Id),
					Isattent: isattent,
				})
			}
		}
	}
	return anchor, nil
}

func (s *Service) live(r *api_models.LiveOrAnchorSearchReq) ([]*api_models.LiveAnchor, error) {
	fName := "models_live"
	resp := make([]*api_models.LiveAnchor, 0)
	lives, err := db_live.GetLivesParam(map[string]interface{}{"title": map[string]interface{}{"like": "%" + r.Keyword + "%"}}, "hot desc,start_stamp desc", r.Page, r.Size)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	if len(lives) < 1 {
		return resp, nil
	}
	tmpIds := make([]int, 0)
	tagIds := make([]int64, 0)
	for i := range lives {
		tmpIds = append(tmpIds, lives[i].Anchorid)
		tagIds = append(tagIds, lives[i].Tag)
	}
	anchorMap, err := s.GetAnchors(0, tmpIds, "", 0, 0)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	tagMap, err := s.GetTags(tagIds)
	if err != nil {
		return nil, fmt.Errorf("%s %s", util.Convert(fName), err.Error())
	}
	getTagInfo := func(id int64) *models_main.ConfigTag {
		for _, tag := range tagMap {
			if int64(tag.Id) == id {
				tag.Operator = "" // 操作人不输出
				return tag
			}
		}
		return nil
	}

	err = copier.Copy(&resp, &lives)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	attentids := make([]int, 0)
	if r.Uid > 0 {
		attentids = cache.GetUserAttentAnchorIds(r.Uid)
	}

	var tempLiveIDS []int64
	for _, v := range lives {
		if v.Ticket > 0 {
			tempLiveIDS = append(tempLiveIDS, v.Liveid)
		}
	}

	//是否支付门票记录
	var ticketLogs []models_live.LiveTicketLog
	if r.Uid > 0 && len(tempLiveIDS) > 0 {
		ticketLogs = db_live.TicketINLives(r.Uid, tempLiveIDS)
	}

	for i := range resp {
		resp[i].Anchor = &api_models.Anchor{}
		resp[i].TagInfo = &models_main.ConfigTag{}
		if _, ok := anchorMap[resp[i].Anchorid]; ok {
			resp[i].Anchor = anchorMap[resp[i].Anchorid]
		}

		resp[i].TagInfo = getTagInfo(resp[i].Tag)

		if string2.IntIsInSlice(attentids, resp[i].Anchor.Id) {
			resp[i].Anchor.Isattent = 1
		}
		resp[i].TicketPaid = 2
		//是否支付门票
		if len(ticketLogs) > 0 {
			for _, v := range ticketLogs {
				if v.Liveid == resp[i].Liveid {
					resp[i].TicketPaid = 1
				}
			}
		}
	}
	return resp, nil
}

func (s *Service) anchor(r *api_models.LiveOrAnchorSearchReq) ([]*api_models.Anchor, error) {
	fName := "anchor"
	args := map[string]interface{}{
		"nick_name": map[string]interface{}{
			"like": "%" + r.Keyword + "%",
		},
		"status":    0,
		"is_anchor": 1,
	}
	users, err := db_main.GetAnchors(args, "online_status asc,regist_time desc", r.Uid, r.Page, r.Size)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	tmpIds := make([]int, 0)
	for i := range users {
		tmpIds = append(tmpIds, users[i].Id)
	}
	resp := make([]*api_models.Anchor, 0)
	err = copier.Copy(&resp, &users)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	profiles, err := db_main.GetUserProfilesParam(map[string]interface{}{"uid": map[string]interface{}{"in": tmpIds}})
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	profileMap := make(map[int]*models_main.UserProfile)
	for i := range profiles {
		profileMap[profiles[i].Uid] = profiles[i]
	}
	attentIds := make([]int, 0)
	if r.Uid > 0 {
		attentIds = cache.GetUserAttentAnchorIds(r.Uid)
	}
	for i := range resp {
		if _, ok := profileMap[resp[i].Id]; ok {
			resp[i].Profile = *profileMap[resp[i].Id]
		}
		resp[i].FansNum = cache.GetFansCount(resp[i].Id)
		if string2.IntIsInSlice(attentIds, resp[i].Id) {
			resp[i].Isattent = 1
		}
	}
	return resp, nil
}
